package com.et.util

import kotlin.experimental.and
import kotlin.experimental.or

/**
 * int format string
 */
fun Int.headInsert2String(c: Char, len: Int): String {
    val s = "$this"
    if (s.length >= len) return s
    val l = len - s.length
    val b = CharArray(l) { c }
    return "${String(b)}$s"
}

fun Int.endInsert2String(c: Char, len: Int): String {
    val s = "$this"
    if (s.length >= len) return s
    val l = len - s.length
    val b = CharArray(l) { c }
    return "$s${String(b)}"
}

fun String.endInsert2String(c: Char, len: Int): String {
    val s = this
    if (s.length >= len) return s
    val l = len - s.length
    val b = CharArray(l) { c }
    return "$s${String(b)}"
}

/**
 * string format
 */
fun String.headInsert2String(char: Char = '0', len: Int): String {
    if (this.length >= len) return this
    val l = len - this.length
    val b = CharArray(l) { char }
    return "${String(b)}$this"
}


fun ByteArray.toHexString(off: Int = 0, len: Int = this.size): String {
    val s = StringBuilder(len.shl(1))
    var i: Int
    for (v in 0 until len) {
        i = this[off + v].toInt()
        if (i < 0) i += 256
        s.append(i.toString(16).headInsert2String(len = 2))
    }
    return s.toString()
}

fun Int.toByteArray(byteArrayLen: Int): ByteArray {
    val b = ByteArray(byteArrayLen)
    var k = this
    for (i in b.indices) {
        b[byteArrayLen - i - 1] = ((k % 10) + (k / 10 % 10 * 16)).toByte()
        k /= 100
    }
    return b
}

fun ByteArray.spiltByteArray(off: Int = 0, length: Int = this.size): ByteArray {
    val b1 = ByteArray(length)
    System.arraycopy(this, off, b1, 0, length)
    return b1
}

fun Byte.parseBoolean(index: Int): Boolean {
    return this.toInt().shr(index) and 1 == 1
}

fun Boolean.insertByte(byte: Byte, i: Int): Byte {
    return if (this) {
        byte or ((1 shl i).toByte())
    } else {
        val mask = (1 shl i).inv()
        byte and mask.toByte()
    }
}

/**
 * max length 8 e.g.11223344 2147483647
 */
fun ByteArray.toBCDInt(off: Int = 0, len: Int = 1): Int {
    var r = 0
    var k: Int
    var b = 1
    var i = len + off - 1
    while (i >= off.coerceAtLeast(off + len - 4)) {
        k = this[i].toInt() and 0xFF
        r += (k - k.shr(4) * 6) * b
        b *= 100
        i--
    }
    return r
}

fun Int.toBCDByte(): Byte {
    if (this < 0) return 0
    if (this > 99) return 0x99.toByte()
    return (this + this / 10 * 6).toByte()
}

/**
 * max length 18 e.g.112233445566778899  9223372036854775807L
 */
fun ByteArray.toBCDLong(off: Int = 0, len: Int = 1): Long {
    var r = 0L
    var k: Long
    var b = 1L
    var i = len + off - 1
    while (i >= off.coerceAtLeast(off + len - 8)) {
        k = this[i].toLong() and 0xFF
        r += (k - k.shr(4) * 6) * b
        b *= 100
        i--
    }
    return r
}

/**
 * max length 6 e.g. 0xff.0x00,0x01>>0xff0001
 */
fun ByteArray.toDecimalInt(off: Int = 0, len: Int = this.size): Int {
    var r = 0
    var k: Int
    var b = 1
    var i = len + off - 1
    while (i >= off.coerceAtLeast(off + len - 3)) {
        k = this[i].toInt() and 0xFF
        r += k * b
        b *= 0x100
        i--
    }
    return r
}

/**
 * max length 14 e.g.0xffffffffffffff
 */
fun ByteArray.toDecimalLong(off: Int = 0, len: Int = this.size): Long {
    var r = 0L
    var k: Long
    var b = 1L
    var i = len + off - 1
    while (i >= off.coerceAtLeast(off + len - 8)) {
        k = this[i].toLong() and 0xFF
        r += k * b
        b *= 0x100
        i--
    }
    return r
}


fun String.violationsTrim(): String {
    return this.replace('*', 'x')
        .replace('/', '_')
        .replace('\\', '_')
        .replace('"', '_')
        .replace(':', '_')
        .replace('?', '_')
        .replace('|', '_')
        .replace('<', '(')
        .replace('>', ')')
        .trim()
}